静态多态性引出了泛型编程的概念。然而，泛型编程没有统一的定义(就像面向对象编程没有统一的定义一样)。根据[CzarneckiEiseneckerGenProg]，定义从使用通用参数编程到寻找最抽象的高效算法表示。书中总结道:

\textit{泛型编程是计算机科学的一个子学科，处理寻找高效算法、数据结构和其他软件概念的抽象表示，以及系统组织... 。泛型编程侧重于表示一系列领域概念。(169 - 170页)}

C++上下文中，泛型编程有时定义为使用模板编程(而面向对象编程认为是使用虚函数编程)，任何C++模板都可以认为是泛型编程的一个实例。然而，专业人员经常认为泛型编程有其他成分:模板必须在一个框架中设计，以支持多种组合。

目前为止，该领域最重要的贡献是标准模板库(Standard Template Library, STL)，后来并入到C++标准库中。STL是一个框架，为对象集合(称为容器)的许多线性数据结构提供了许多有用的操作(称为算法)，算法和容器都是模板，但关键是算法不是容器的成员函数。这些算法以通用的方式编写，因此可以用于任何容器(以及元素的线性集合)。为此，STL的设计者确定了一个抽象的迭代器概念，可以为任何类型的线性集合提供迭代器。本质上，容器操作的集合特定方面已经分解到迭代器的功能中了。

因此，可以实现这样的操作，比如：计算序列中的最大值，而不需要知道值如何存储在序列中的:

\begin{lstlisting}[style=styleCXX]
template<typename Iterator>
Iterator max_element (Iterator beg, // refers to start of collection
					  Iterator end) // refers to end of collection
{
	// use only certain Iterator operations to traverse all elements
	// of the collection to find the element with the maximum value
	// and return its position as Iterator
	...
}
\end{lstlisting}

与为每个线性容器提供所有有用的操作(如max\_element())不同，容器只需要提供一个迭代器类型来遍历所包含的值序列，以及创建迭代器的相应成员函数:

\begin{lstlisting}[style=styleCXX]
namespace std {
	template<typename T, ...>
	class vector {
		public:
		using const_iterator = ...; // implementation-specific iterator
		... // type for constant vectors
		const_iterator begin() const; // iterator for start of collection
		const_iterator end() const; // iterator for end of collection
		...
	};

	template<typename T, ...>
	class list {
		public:
		using const_iterator = ...; // implementation-specific iterator
		... // type for constant lists
		const_iterator begin() const; // iterator for start of collection
		const_iterator end() const; // iterator for end of collection
		...
	};
}
\end{lstlisting}

现在，可以通过max\_element()操作，以集合的开始和结束为参数来找到集合中的最大值(空集合的特殊处理省略了):

\hspace*{\fill} \\ %插入空行
\noindent
\textit{poly/printmax.cpp}
\begin{lstlisting}[style=styleCXX]
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
#include "MyClass.hpp"

template<typename T>
void printMax (T const& coll)
{
	// compute position of maximum value
	auto pos = std::max_element(coll.begin(),coll.end());
	
	// print value of maximum element of coll (if any):
	if (pos != coll.end()) {
		std::cout << *pos << ’\n’;
	}
	else {
		std::cout << "empty" << ’\n’;
	}
}

int main()
{
	std::vector<MyClass> c1;
	std::list<MyClass> c2;
	...
	printMax(c1);
	printMax(c2);
}
\end{lstlisting}

通过用这些迭代器参数化其操作，STL避免了操作定义数量的激增。开发者也不再为每个容器实现每个操作，而是只实现一次算法，每个容器就可以使用。通用的粘合剂是迭代器，因为迭代器有一个特定的接口，该接口由容器提供，并由算法使用。这个接口通常称为概念，表示模板必须满足的一组约束，以适应这个框架。此外，这个概念对其他操作和数据结构开放。

可能还记得在18.4节之前描述了一个概念语言特性(附录E中有更详细的描述)。语言特性与这里的概念完全对应，术语概念由STL的设计师首先引入，以形式化他们的工作。此后不久，开始尝试在模板中明确这些概念。

即将到来的语言特性将帮助我们指定和检查迭代器的要求(因为有不同的迭代器类别，如前向迭代器和双向迭代器，将涉及多个相应的概念;参见第E.3.1节)。如今的C++中，这些概念大多隐含在泛型库(尤其是标准C++库)的规范中。幸运的是，一些特性和技术(例如，static\_assert和SFINAE)允许自动检查类型。

原则上，类似于STL的方法这样的功能可以通过动态多态性实现。但在实践中，因为与虚函数调用机制相比，其用途有限，迭代器的概念过于轻量级。添加基于虚拟函数的接口层很可能会大大降低操作速度(甚至更慢)。

泛型编程之所以实用，是因为依赖于静态多态性，该多态性在编译时解析接口。另一方面，编译时解析接口的需求也需要相应的设计原则，这些原则与面向对象的设计原则不同。许多重要的通用设计原则将在本书的其余部分进行描述。此外，附录E通过描述对概念中的概念的直接语言支持，更深入地探讨了泛型编程。























